﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace landlord2lib
{
    public class CardGroupGourd : CardGroup
    {
        public CardGroupGourd(Card[] cards)
        {
            m_cards = cards;
        }

        public override bool IsValid()
        {
            try
            {
                if (m_cards.Length != CardGroupGourd.CardCount) return false;
                foreach (Card card in m_cards) card.Reset();

                Card cardReal1 = null, cardReal2 = null;
                foreach (Card card in m_cards)
                {
                    if (!card.IsJoker)
                    {
                        if (cardReal1 == null) cardReal1 = card;
                        else if (cardReal2 == null)
                        {
                            if (cardReal1.ComparePoint != card.ComparePoint) cardReal2 = card;
                        }
                        else break;
                    }
                }
                if (cardReal1 != null && cardReal2 != null)
                {
                    if (cardReal1.CompareTo(cardReal2) < 0)
                    {
                        Card cardTemp = cardReal2;
                        cardReal2 = cardReal1;
                        cardReal1 = cardTemp;
                    }

                    int count1 = 0, count2 = 0;
                    foreach (Card card in m_cards)
                    {
                        if (card.ComparePoint == cardReal1.ComparePoint) count1++;
                        if (card.ComparePoint == cardReal2.ComparePoint) count2++;
                    }
                    foreach (Card card in m_cards)
                    {
                        if (card.IsJoker)
                        {
                            if (count1 != 3) count1++;
                            else if (count2 != 3) count2++;
                        }
                    }
                    return (count1 == 3 && count2 == 2) || (count1 == 2 && count2 == 3);
                }
                return false;
            }
            catch
            {
                return false;
            }
        }

        public override int CompareTo(CardGroup other)
        {
            try
            {
                if (other is CardGroupGourd)
                {
                    CardGroupGourd o = (CardGroupGourd)other;
                    return GetCompareCard().CompareTo(o.GetCompareCard());
                }
                else return -1;
            }
            catch
            {
                return 0;
            }
        }

        private Card GetCompareCard()
        {
            Card cardReal1 = null, cardReal2 = null;
            foreach (Card card in m_cards)
            {
                if (cardReal1 == null) cardReal1 = card;
                else if (cardReal2 == null)
                {
                    if (cardReal1.ComparePoint != card.ComparePoint) cardReal2 = card;
                }
                else break;
            }

            int count1 = 0, count2 = 0;
            foreach (Card card in m_cards)
            {
                if (card.ComparePoint == cardReal1.ComparePoint) count1++;
                if (card.ComparePoint == cardReal2.ComparePoint) count2++;
            }
            return count1 > count2 ? cardReal1 : cardReal2;
        }

        public static int CardCount
        {
            get
            {
                return 5;
            }
        }

        public static HintCardCollection Hint(Card[] handCards, CardGroupGourd lastGroup)
        {
            HintCardCollection result = new HintCardCollection();
            try
            {
                CardStack stack = new CardStack(handCards);
                CardPoint minPt = lastGroup.GetCompareCard().Point;

                HintCardCollection resultTriple = new HintCardCollection();
                for (int pt = (int)minPt + 1; pt <= (int)CardPoint.Card2; pt++)
                {
                    if (stack[pt].Count == 3)
                    {
                        List<Card> cards = new List<Card>();
                        for (int i = 0; i < 3; i++) cards.Add(stack[pt][i]);
                        resultTriple.AddHint(cards.ToArray());
                    }
                }

                HintCardCollection resultPair = new HintCardCollection();
                for (int pt = (int)CardPoint.Card3; pt <= (int)CardPoint.Card2; pt++)
                {
                    if (stack[pt].Count == 2)
                    {
                        List<Card> cards = new List<Card>();
                        for (int i = 0; i < 2; i++) cards.Add(stack[pt][i]);
                        resultPair.AddHint(cards.ToArray());
                    }
                }

                while (true)
                {
                    Card[] cardsPair = resultPair.NextHint();
                    if (cardsPair == null) break;
                    while (true)
                    {
                        Card[] cardsTriple = resultTriple.NextHint();
                        if (cardsTriple == null) break;
                        CardPoint? ptTriple = GetCardsPoint(cardsTriple);
                        CardPoint? ptPair = GetCardsPoint(cardsPair);
                        if (ptTriple != null && ptPair != null && ptTriple.Value != ptPair.Value)
                        {
                            List<Card> cards = new List<Card>();
                            cards.AddRange(cardsTriple);
                            cards.AddRange(cardsPair);
                            result.AddHint(cards.ToArray());
                        }
                    }
                }

                return result;
            }
            catch
            {
                return result;
            }
        }

        private static CardPoint? GetCardsPoint(Card[] cards)
        {
            foreach (Card card in cards)
            {
                if (card.IsJoker) continue;
                return card.Point;
            }
            return null;
        }
    }
}
